package org.dfzt.modules.quartz.service.impl;

import java.util.List;

import cn.hutool.core.util.IdUtil;
import com.dangdang.ddframe.job.api.simple.SimpleJob;
import com.dangdang.ddframe.job.lite.config.LiteJobConfiguration;
import com.dangdang.ddframe.job.lite.lifecycle.api.JobOperateAPI;
import com.dangdang.ddframe.job.lite.spring.api.SpringJobScheduler;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;
import com.dangdang.ddframe.job.util.env.IpUtils;
import org.dfzt.common.constant.CommonConstant;
import org.dfzt.modules.quartz.entity.QuartzJob;
import org.dfzt.modules.quartz.mapper.QuartzJobMapper;
import org.dfzt.modules.quartz.service.IQuartzJobService;
import org.dfzt.modules.quartz.util.JobListener;
import org.dfzt.modules.quartz.util.JobUtil;
import com.google.common.base.Optional;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.SchedulerException;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;


/**
 * @Description: 定时任务在线管理
 */

@Service
public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob> implements IQuartzJobService {
	private static final Log log = LogFactory.getLog(QuartzJobServiceImpl.class);

	@Resource
	private QuartzJobMapper quartzJobMapper;

	@Resource
    private ZookeeperRegistryCenter zookeeperRegistryCenter;

	@Resource
    private JobOperateAPI jobOperateAPI;

    @Override
    public List<QuartzJob> findByJobName(String jobName) {
        return quartzJobMapper.findByJobName(jobName);
    }

    @Override
	public List<QuartzJob> findByJobClassName(String jobClassName) {
		return quartzJobMapper.findByJobClassName(jobClassName);
	}

	/**
	 * 保存定时任务
     * 由状态决定任务启停
     * @date 2020/1/9
	 */
	@Override
	public boolean saveAndScheduleJob(QuartzJob quartzJob) throws Exception {
		if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
		    if (StringUtils.isBlank(quartzJob.getParameter())){
		        quartzJob.setParameter(IdUtil.simpleUUID());
            }
			// 定时器添加
			this.schedulerAdd(quartzJob.getJobName().trim(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
		}
		// DB设置修改
		quartzJob.setDelFlag(CommonConstant.DEL_FLAG_0);
		return this.save(quartzJob);
	}

	/**
	 * 恢复启动定时任务
	 */
	@Override
	public boolean resumeJob(QuartzJob quartzJob) throws Exception {
		schedulerAdd(quartzJob.getJobName(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
		quartzJob.setStatus(CommonConstant.STATUS_NORMAL);
		return this.updateById(quartzJob);
	}

	/**
     * 项目重启，启动所有状态为正常的任务
     * @date 2020-1-10
     * */
    @Override
    public void startJob() {
        List<QuartzJob> list = quartzJobMapper.findByStatus();
        if (list!=null && list.size()>0){
            for (QuartzJob job: list){
                try {
                    this.schedulerAdd(job.getJobName(), job.getJobClassName(), job.getCronExpression(), job.getParameter());
                } catch (Exception e){
                    log.error("启动上次正在运行的定时任务失败",e);
                    quartzJobMapper.updateStatusById(job.getId());
                }
            }
        } else {
            log.info("未找到正在运行的定时任务");
        }
    }

    @Override
    public void startJob(QuartzJob job) throws Exception {
        if (CommonConstant.STATUS_NORMAL.equals(job.getStatus())) {
            // 定时器添加
            this.schedulerAdd(job.getJobName().trim(), job.getJobClassName().trim(), job.getCronExpression().trim(), job.getParameter());
        }
    }

    /**
	 * 编辑定时任务
     * 由状态决定任务启停
	 * @throws SchedulerException
     * @date 2020/1/9
	 */
	@Override
	public boolean editAndScheduleJob(QuartzJob quartzJob, String jobName) throws Exception {
		if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
		    //验证参数是否为空，如果为空，设置自定义id
            if (StringUtils.isBlank(quartzJob.getParameter())){
                quartzJob.setParameter(IdUtil.simpleUUID());
            }
		    //先删除老的定时任务，再添加新的
            jobOperateAPI.remove(Optional.of(jobName), Optional.of(IpUtils.getIp()));
			schedulerAdd(quartzJob.getJobName().trim(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
		}else{
            jobOperateAPI.remove(Optional.of(jobName), Optional.of(IpUtils.getIp()));
		}
		return this.updateById(quartzJob);
	}

	/**
	 * 删除&停止定时任务
     * @date 2020/1/9
	 */
	@Override
	public boolean deleteAndStopJob(QuartzJob job) {
	    try {
            jobOperateAPI.remove(Optional.of(job.getJobName()), Optional.absent());
        } catch (Exception e){
	        log.error("未在服务器上找到此任务");
        }
		return this.removeById(job.getId());
	}

	/**
	 * 添加定时任务
	 * 
	 * @param jobClassName
	 * @param cronExpression
	 * @param parameter
	 */
	public void schedulerAdd(String jobName, String jobClassName, String cronExpression, String parameter) throws Exception {
        LiteJobConfiguration jobConfig = JobUtil.simpleJobConfigBuilder(jobName,
                //定时任务执行类
                getClass(jobClassName).getClass(),
                //切片数
                1,
                //cron表达式
                cronExpression,
                //作为自定义参数传递
                parameter
        )
                //当jobName相同，修改其它参数时，你会发现，重新启动应用执行并没有生效，依然保留原有参数
                //因为zookeeper 注册中心会持久化这个分片相关信息
                //需要overwrite设置为true即可
                .overwrite(true)
                .build();

        new SpringJobScheduler(getClass(jobClassName).getClass().newInstance(), zookeeperRegistryCenter, jobConfig,
                new JobListener(3000,3000)).init();
        log.info("启动定时任务【" + jobName + "】成功");
	}

	private SimpleJob getClass(String classname) throws Exception {
		Class<?> class1 = Class.forName(classname);
		return (SimpleJob) class1.newInstance();
	}
}
